#!/usr/bin/pypy

# BigData course project
# Serial version of training algorithm for SOM
# Sparse vector implementation 

import sys
import util
from util import log
import numpy as np
from numpy import *

class SparseVec:
    # we know how to build the sparse vector from a string with 
    # following syntax:
    # <index1> <value1> <index2> <value2> ... <indexN> <valueN>    
    #
    # where is at most the dimension for this vector.
    # Purpose is to create numpy array representation, which is not
    # sparse, but aims to speed up computations against other arrays
    # (so we avoid converting back and forth between sparse and dense)
    #
    def __init__(self, n, s):
        self.v = zeros(n, dtype=float64)
        toks = s.split()
        for i in xrange(0,len(toks),2):
            try:
                self.v[int(toks[i])] = float(toks[i+1])
            except:
                log("Failed to parse sparse vector spec %s at %i: %s\n", 
                    s, i, sys.exc_info())
                raise

    def dump(self):
        dump_tup = lambda t: "%d %2.6f" % t
        fst = lambda t: t[0]
        idx_val = filter(lambda x: x[1]>0, zip(xrange(len(self.v)), self.v))
        return " ".join(map(dump_tup, idx_val, key=fst))

    # knows how to efficiently calculate the norm against a numpy array
    # since we are importing everything from numpy, the functions sqrt, sum, and the
    # minus operator should all come from there.
    def dist(self, arr):
        return sqrt(sum((self.v - arr)**2))

    # substract the input array to itself and returns resulting new array
    def minus(self, arr):
        return self.v - arr
